#!/usr/bin/env python
#
# Copyright 2007 Matthew Stump
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.

#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

import wsgiref.handlers, csv, re
from google.appengine.ext import webapp
from google.appengine.api import urlfetch
from StringIO import StringIO
from datetime import *


YHOO_URL = "http://ichart.finance.yahoo.com/table.csv?s=%s&a=%s&b=%s&c=%s&g=v&ignore=.csv"
GOOG_URL = "http://finance.google.com/finance?q=%s"
TICKER_REGEX = re.compile("[A-Za-z]{1,4}")
GOOG_EVENT_REGEX = re.compile("_chartConfigObject\.corpActionsArray = eval\('\((.*)\)'\);")
unzip = lambda l:tuple(zip(*l))


class MainHandler(webapp.RequestHandler):

    def get(self):
        ticker = self.request.get('t')
        if ticker == '' or not TICKER_REGEX.match(ticker):
            self.response.out.write("--")
            return

        mode = self.request.get('dm')
        year = self.request.get('y')
        month = self.request.get('m')
        day = self.request.get('d')
        if mode == 'r':
            try:
                startDate = datetime(int(year), int(month), int(day))
            except:
                startDate = datetime.now() - timedelta(365 * 10)

            today = datetime.today()
            headers = ["Date", "Dividend Payout", "Split Multiplier"]

            filteredData = fetch_goog_data(ticker, startDate, today)
            filteredData = [ "%s,%s" % (x[0].strftime("%Y-%m-%d"), ",".join(x[1:])) for x in filteredData ]
            filteredData.insert(0, ",".join(headers))

            output = "\n".join(filteredData)
            self.response.out.write(output)

        elif mode == "d4l":
            startDate = datetime.now() - timedelta(365 * 11)
            endDate = datetime.now() - timedelta(365)
            filteredData = fetch_goog_data(ticker, startDate, endDate)
            year_buckets = {}        

            for (date, dividend, _) in filteredData:
                if year_buckets.has_key(date.year):
                    year_buckets[date.year] += dividend
                else:
                    year_buckets[date.year] = dividend

            del filteredData
            years = year_buckets.keys()
            years.sort()
            years.reverse()
            values = ",".join([ str(year_buckets[x]) for x in years ])
            years = ",".join(map(str, years))
            self.response.out.write("<html><body><pre>%s</pre></body></html>" % "\n".join([years, values]))
            
        else:
            tenYago = (datetime.now() - timedelta(365 * 11)).year
            result = urlfetch.fetch(YHOO_URL % (ticker, "00", "01", tenYago))
            csv_reader = csv.reader(StringIO(result.content))
            output = parse_csv_data(csv_reader)
            self.response.out.write(output)


def fetch_goog_data(ticker, startDate, endDate):
    eventData = eval(GOOG_EVENT_REGEX.search(urlfetch.fetch(GOOG_URL % ticker).content).group(1))

    filteredData = []
    for event in eventData:
        if event.has_key('_payable_date'):
            date = datetime.fromtimestamp(float(event['_payable_date']))
            if date < endDate and date > startDate:
                filteredData.append([date, float(event['_amount']), 1.0])

        elif event.has_key('_new_shares'):
            date = datetime.fromtimestamp(float(event['_date']))
            if date < endDate and date > startDate:
                filteredData.append([ date, 0.0, float(event['_new_shares']) / float(event['_old_shares']) ])

    del eventData

    filteredData.sort(lambda x, y: cmp(x[0], y[0]))
    return filteredData


def parse_csv_data(csv_reader, header=True):
    if header:
        csv_reader.next()

    now = datetime.now()
    oneYdelta = timedelta(365)
    oneYago = now - oneYdelta

    previous365 = []
    year_buckets = {}

    def year_over_growth():
        growth = {}
        for y in year_buckets.keys():
            if y != now.year and year_buckets.has_key(y - 1):
                curr = sum_dividend(year_buckets[y])
                prev = sum_dividend(year_buckets[y - 1])
                growth[y] = ((curr - prev) / prev)

        #if len(year_buckets[oneYago.year]) > len(year_buckets[now.year]):
        #    div_remaining = len(year_buckets[oneYago.year]) - len(year_buckets[now.year])
        #    last_payment = 

        if len(year_buckets.keys()) >= 5:
            fiveYavg = sum([growth.get(x, 0.0) for x in xrange(oneYago.year - 5, oneYago.year)]) / 5.0

            if len(year_buckets.keys()) >= 10:
                tenYavg = sum(growth.values()) / 10.0
            else:
                tenYavg = "--"
        else:
            fiveYavg = "--"
            tenYavg = "--"

        return (fiveYavg, tenYavg)
        

    def sum_dividend(div_list):
        total = 0.0
        for (_, div) in div_list:
           total += div

        return total

    def parse((date, value)):
      date = datetime.strptime(date,  "%Y-%m-%d")
      value = float(value)

      if year_buckets.has_key(date.year):
          year_buckets[date.year].append((date, value))

      else:
          year_buckets[date.year] = [(date, value)]

      return (date, value)

    payments = [ parse(x) for x in csv_reader ]

    if year_buckets.has_key(oneYago.year):
        div_frequency = len(year_buckets[oneYago.year])
    else:
        div_frequency = "--"
    
    if len(payments) > 0:
        (last_date, last_payment) = payments[0]
        last_date = last_date.strftime("%Y-%m-%d")
    else:
        (last_date, last_payment) = ("--", "--")

    (fiveYavg, tenYavg) = year_over_growth()
    
    return "%s,%s,%s,%s,%s" % (last_payment, last_date, div_frequency, fiveYavg, tenYavg)



def main():
    application = webapp.WSGIApplication([('/', MainHandler)], debug=True)
    wsgiref.handlers.CGIHandler().run(application)


if __name__ == '__main__':
    main()
